package com.christina.engine.processing.model;

import lombok.Getter;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 处理结果数据模型
 * 包含处理器执行结果的所有相关信息
 */
@Getter
public class ProcessingResult {
    
    private final boolean success;
    private final boolean shouldContinue;
    private final String errorMessage;
    private final Throwable exception;
    private final Map<String, Object> resultData;
    private final Map<String, Object> metadata;
    private final LocalDateTime timestamp;
    private final String processorName;
    private final long executionTimeMs;
    
    private ProcessingResult(Builder builder) {
        this.success = builder.success;
        this.shouldContinue = builder.shouldContinue;
        this.errorMessage = builder.errorMessage;
        this.exception = builder.exception;
        this.resultData = new HashMap<>(builder.resultData);
        this.metadata = new HashMap<>(builder.metadata);
        this.timestamp = builder.timestamp != null ? builder.timestamp : LocalDateTime.now();
        this.processorName = builder.processorName;
        this.executionTimeMs = builder.executionTimeMs;
    }
    
    // 自定义getter方法返回防御性拷贝
    public Map<String, Object> getResultData() { 
        return new HashMap<>(resultData); 
    }
    
    public Map<String, Object> getMetadata() { 
        return new HashMap<>(metadata); 
    }
    
    // 便利方法
    public <T> T getResultData(String key, Class<T> type) {
        Object value = resultData.get(key);
        if (value != null && type.isInstance(value)) {
            return type.cast(value);
        }
        return null;
    }
    
    public boolean hasResultData(String key) {
        return resultData.containsKey(key);
    }
    
    public <T> T getMetadata(String key, Class<T> type) {
        Object value = metadata.get(key);
        if (value != null && type.isInstance(value)) {
            return type.cast(value);
        }
        return null;
    }
    
    public boolean hasMetadata(String key) {
        return metadata.containsKey(key);
    }
    
    public boolean isFailure() {
        return !success;
    }
    
    public boolean shouldStop() {
        return !shouldContinue;
    }
    
    public boolean hasError() {
        return errorMessage != null || exception != null;
    }
    
    // Builder模式
    public static class Builder {
        private boolean success = true;
        private boolean shouldContinue = true;
        private String errorMessage;
        private Throwable exception;
        private Map<String, Object> resultData = new HashMap<>();
        private Map<String, Object> metadata = new HashMap<>();
        private LocalDateTime timestamp;
        private String processorName;
        private long executionTimeMs = 0;
        private boolean explicitSuccessSet = false; // 跟踪是否明确设置了success
        
        public Builder success(boolean success) {
            this.success = success;
            this.explicitSuccessSet = true; // 标记为明确设置
            return this;
        }
        
        public Builder shouldContinue(boolean shouldContinue) {
            this.shouldContinue = shouldContinue;
            return this;
        }
        
        public Builder errorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
            return this;
        }
        
        public Builder exception(Throwable exception) {
            this.exception = exception;
            return this;
        }
        
        public Builder resultData(String key, Object value) {
            this.resultData.put(key, value);
            return this;
        }
        
        public Builder resultData(Map<String, Object> data) {
            this.resultData.putAll(data);
            return this;
        }
        
        public Builder metadata(String key, Object value) {
            this.metadata.put(key, value);
            return this;
        }
        
        public Builder metadata(Map<String, Object> metadata) {
            this.metadata.putAll(metadata);
            return this;
        }
        
        public Builder timestamp(LocalDateTime timestamp) {
            this.timestamp = timestamp;
            return this;
        }
        
        public Builder processorName(String processorName) {
            this.processorName = processorName;
            return this;
        }
        
        public Builder executionTimeMs(long executionTimeMs) {
            this.executionTimeMs = executionTimeMs;
            return this;
        }
        
        public ProcessingResult build() {
            // 如果有异常或错误消息，自动设置为失败
            // 注意：这个逻辑可能会被某些处理器重写，比如ContextProcessor在handleError中
            // 明确设置了success=true，即使有错误信息
            if (exception != null || errorMessage != null) {
                // 无论是否明确设置了success，只要有错误消息或异常，都自动设置为失败
                this.success = false;
            }
            
            return new ProcessingResult(this);
        }
    }
    
    public static Builder builder() {
        return new Builder();
    }
    
    // 静态工厂方法 - 常用结果类型
    public static ProcessingResult success() {
        return builder()
                .success(true)
                .shouldContinue(true)
                .build();
    }
    
    public static ProcessingResult success(String processorName) {
        return builder()
                .success(true)
                .shouldContinue(true)
                .processorName(processorName)
                .build();
    }
    
    public static ProcessingResult successWithData(String key, Object value) {
        return builder()
                .success(true)
                .shouldContinue(true)
                .resultData(key, value)
                .build();
    }
    
    public static ProcessingResult successWithData(Map<String, Object> data) {
        return builder()
                .success(true)
                .shouldContinue(true)
                .resultData(data)
                .build();
    }
    
    public static ProcessingResult successAndStop() {
        return builder()
                .success(true)
                .shouldContinue(false)
                .build();
    }
    
    public static ProcessingResult successAndStop(String processorName) {
        return builder()
                .success(true)
                .shouldContinue(false)
                .processorName(processorName)
                .build();
    }
    
    public static ProcessingResult failure(String errorMessage) {
        return builder()
                .success(false)
                .shouldContinue(false)
                .errorMessage(errorMessage)
                .build();
    }
    
    public static ProcessingResult failure(String errorMessage, String processorName) {
        return builder()
                .success(false)
                .shouldContinue(false)
                .errorMessage(errorMessage)
                .processorName(processorName)
                .build();
    }
    
    public static ProcessingResult failure(Throwable exception) {
        return builder()
                .success(false)
                .shouldContinue(false)
                .exception(exception)
                .errorMessage(exception.getMessage())
                .build();
    }
    
    public static ProcessingResult failure(String errorMessage, Throwable exception) {
        return builder()
                .success(false)
                .shouldContinue(false)
                .errorMessage(errorMessage)
                .exception(exception)
                .build();
    }
    
    public static ProcessingResult failure(String errorMessage, Throwable exception, String processorName) {
        return builder()
                .success(false)
                .shouldContinue(false)
                .errorMessage(errorMessage)
                .exception(exception)
                .processorName(processorName)
                .build();
    }
    
    public static ProcessingResult failureButContinue(String errorMessage) {
        return builder()
                .success(false)
                .shouldContinue(true)
                .errorMessage(errorMessage)
                .build();
    }
    
    public static ProcessingResult failureButContinue(String errorMessage, String processorName) {
        return builder()
                .success(false)
                .shouldContinue(true)
                .errorMessage(errorMessage)
                .processorName(processorName)
                .build();
    }
    
    // 结果合并方法
    public ProcessingResult mergeWith(ProcessingResult other) {
        if (other == null) {
            return this;
        }
        
        Builder builder = ProcessingResult.builder()
                .success(this.success && other.success)
                .shouldContinue(this.shouldContinue && other.shouldContinue)
                .executionTimeMs(this.executionTimeMs + other.executionTimeMs);
        
        // 合并结果数据
        builder.resultData(this.resultData);
        builder.resultData(other.resultData);
        
        // 合并元数据
        builder.metadata(this.metadata);
        builder.metadata(other.metadata);
        
        // 处理错误信息
        if (this.errorMessage != null && other.errorMessage != null) {
            builder.errorMessage(this.errorMessage + "; " + other.errorMessage);
        } else if (this.errorMessage != null) {
            builder.errorMessage(this.errorMessage);
        } else if (other.errorMessage != null) {
            builder.errorMessage(other.errorMessage);
        }
        
        // 处理异常（保留第一个异常）
        if (this.exception != null) {
            builder.exception(this.exception);
        } else if (other.exception != null) {
            builder.exception(other.exception);
        }
        
        // 处理处理器名称
        if (this.processorName != null && other.processorName != null) {
            builder.processorName(this.processorName + "+" + other.processorName);
        } else if (this.processorName != null) {
            builder.processorName(this.processorName);
        } else if (other.processorName != null) {
            builder.processorName(other.processorName);
        }
        
        return builder.build();
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ProcessingResult that = (ProcessingResult) o;
        return success == that.success &&
                shouldContinue == that.shouldContinue &&
                executionTimeMs == that.executionTimeMs &&
                Objects.equals(errorMessage, that.errorMessage) &&
                Objects.equals(resultData, that.resultData) &&
                Objects.equals(metadata, that.metadata) &&
                Objects.equals(processorName, that.processorName);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(success, shouldContinue, errorMessage, resultData, 
                          metadata, processorName, executionTimeMs);
    }
    
    @Override
    public String toString() {
        return "ProcessingResult{" +
                "success=" + success +
                ", shouldContinue=" + shouldContinue +
                ", processorName='" + processorName + '\'' +
                ", executionTimeMs=" + executionTimeMs +
                ", hasError=" + hasError() +
                ", resultDataKeys=" + resultData.keySet() +
                ", metadataKeys=" + metadata.keySet() +
                '}';
    }
}